﻿using Geometry;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UserInterface.Primitives;

namespace UserInterface.Tests.Primitives
{
	[TestClass]
	public class GridFieldTests
	{
        #region Autos
        [TestMethod]
        public void GridField_FixedSizeWontStretch()
        {
            var layout = new GridField()
            {
                new GridBand() { Length = 10, Unit = GridBandUnit.Points },
                new GridBand() { Length = 10, Unit = GridBandUnit.Points }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 5f);
            layout.PushSingleBandAutoItem(0, 10f);
            layout.PushSingleBandAutoItem(0, 15f);
            layout.PushSingleBandAutoItem(1, 15f);
            layout.PushSingleBandAutoItem(1, 10f);
            layout.PushSingleBandAutoItem(1, 5f);

            layout.SetAvailableLengthForPercents(50f);

            Assert.AreEqual(10f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(10f, layout.GetAvailableSpan(1, 1));

            layout.SetArrangeLengthForPercents(50f);

            Assert.AreEqual(new Interval(0f, 10f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(10f, 20f), layout.GetArrangeInterval(1, 1));
        }

        [TestMethod]
        public void GridField_AutoSizeNonSpanningItems()
        {
            var layout = new GridField()
            {
                new GridBand() { Unit = GridBandUnit.Auto },
                new GridBand() { Unit = GridBandUnit.Auto }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 10f);
            layout.PushSingleBandAutoItem(0, 5f);
            layout.PushSingleBandAutoItem(1, 5f);
            layout.PushSingleBandAutoItem(1, 10f);

            layout.SetAvailableLengthForPercents(50f);

            Assert.AreEqual(10f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(10f, layout.GetAvailableSpan(1, 1));

            layout.SetArrangeLengthForPercents(50f);

            Assert.AreEqual(new Interval(0f, 10f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(10f, 20f), layout.GetArrangeInterval(1, 1));
        }

        [TestMethod]
        public void GridField_AutoSizeWithSpanningItems()
        {
            var layout = new GridField()
            {
                new GridBand() { Unit = GridBandUnit.Auto },
                new GridBand() { Unit = GridBandUnit.Auto }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 10f);
            layout.PushSingleBandAutoItem(0, 5f);
            layout.PushSingleBandAutoItem(1, 10f);

            layout.PushSpanningAutoItem(0, 2, 30f);
            layout.PushSpanningAutoItem(0, 2, 25f);

            layout.SetAvailableLengthForPercents(50f);

            Assert.AreEqual(15f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(15f, layout.GetAvailableSpan(1, 1));

            layout.SetArrangeLengthForPercents(50f);

            Assert.AreEqual(new Interval(0f, 15f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(15f, 30f), layout.GetArrangeInterval(1, 1));
        }
        #endregion

        #region Percents
        [TestMethod]
        public void GridField_SimplePercent()
        {
            var layout = new GridField()
            {
                new GridBand() { Unit = GridBandUnit.Auto },
                new GridBand() { Length = 2, Unit = GridBandUnit.Percent },
                new GridBand() { Length = 1, Unit = GridBandUnit.Percent },
                new GridBand() { Unit = GridBandUnit.Auto }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 10f);
            layout.PushSingleBandAutoItem(3, 10f);

            layout.SetAvailableLengthForPercents(50f);

            Assert.AreEqual(10f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(20f, layout.GetAvailableSpan(1, 1));
            Assert.AreEqual(10f, layout.GetAvailableSpan(2, 1));
            Assert.AreEqual(10f, layout.GetAvailableSpan(3, 1));

            layout.SetArrangeLengthForPercents(50f);

            Assert.AreEqual(new Interval(0f, 10f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(10f, 30f), layout.GetArrangeInterval(1, 1));
            Assert.AreEqual(new Interval(30f, 40f), layout.GetArrangeInterval(2, 1));
            Assert.AreEqual(new Interval(40f, 50f), layout.GetArrangeInterval(3, 1));
        }

        [TestMethod]
        public void GridField_MinWidthPercent()
        {
            var layout = new GridField()
            {
                new GridBand() { Unit = GridBandUnit.Auto },
                new GridBand() { Length = 2, Unit = GridBandUnit.Percent },
                new GridBand() { Length = 1, Unit = GridBandUnit.Percent, Minimum = 15f },
                new GridBand() { Unit = GridBandUnit.Auto }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 10f);
            layout.PushSingleBandAutoItem(3, 10f);

            layout.SetAvailableLengthForPercents(50f);

            Assert.AreEqual(10f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(15f, layout.GetAvailableSpan(1, 1));
            Assert.AreEqual(15f, layout.GetAvailableSpan(2, 1));
            Assert.AreEqual(10f, layout.GetAvailableSpan(3, 1));

            layout.SetArrangeLengthForPercents(50f);

            Assert.AreEqual(new Interval(0f, 10f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(10f, 25f), layout.GetArrangeInterval(1, 1));
            Assert.AreEqual(new Interval(25f, 40f), layout.GetArrangeInterval(2, 1));
            Assert.AreEqual(new Interval(40f, 50f), layout.GetArrangeInterval(3, 1));
        }

        [TestMethod]
        public void GridField_SpanningThroughPercentsDoesAffectLanes()
        {
            var layout = new GridField()
            {
                new GridBand() { Unit = GridBandUnit.Auto },
                new GridBand() { Length = 1, Unit = GridBandUnit.Percent },
                new GridBand() { Unit = GridBandUnit.Auto }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 20f);
            layout.PushSingleBandAutoItem(1, 20f);
            layout.PushSingleBandAutoItem(2, 20f);

            layout.PushSpanningAutoItem(0, 2, 100f);
            layout.PushSpanningAutoItem(1, 2, 100f);

            layout.SetAvailableLengthForPercents(150f);

            Assert.AreEqual(20f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(110f, layout.GetAvailableSpan(1, 1));
            Assert.AreEqual(20f, layout.GetAvailableSpan(2, 1));

            layout.SetArrangeLengthForPercents(150f);

            Assert.AreEqual(new Interval(0f, 20f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(20f, 130f), layout.GetArrangeInterval(1, 1));
            Assert.AreEqual(new Interval(130f, 150f), layout.GetArrangeInterval(2, 1));
        }

        [TestMethod]
        public void GridField_InsufficientAvailableSpace()
        {
            var layout = new GridField()
            {
                new GridBand() { Unit = GridBandUnit.Auto },
                new GridBand() { Length = 1, Unit = GridBandUnit.Percent },
                new GridBand() { Unit = GridBandUnit.Auto }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 20f);
            layout.PushSingleBandAutoItem(1, 20f);
            layout.PushSingleBandAutoItem(2, 20f);

            layout.SetAvailableLengthForPercents(30f);

            Assert.AreEqual(20f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(0f, layout.GetAvailableSpan(1, 1));
            Assert.AreEqual(20f, layout.GetAvailableSpan(2, 1));

            layout.CalculatePercentsDesiredSize();

            Assert.AreEqual(40f, layout.DesiredLength);

            layout.SetArrangeLengthForPercents(30f);

            Assert.AreEqual(new Interval(0f, 20f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(20f, 20f), layout.GetArrangeInterval(1, 1));
            Assert.AreEqual(new Interval(20f, 40f), layout.GetArrangeInterval(2, 1));
        }
        #endregion

        #region UseCases
        [TestMethod]
        public void GridField_UseCase_ScrollBar()
        {
            var layout = new GridField()
            {
                new GridBand() { Unit = GridBandUnit.Auto },
                new GridBand() { Length = 1, Unit = GridBandUnit.Percent },
                new GridBand() { Unit = GridBandUnit.Auto }
            };

            layout.Reset();

            layout.PushSingleBandAutoItem(0, 24f);
            layout.PushSingleBandAutoItem(1, 24f);
            layout.PushSingleBandAutoItem(2, 24f);

            layout.SetAvailableLengthForPercents(100f);

            Assert.AreEqual(24f, layout.GetAvailableSpan(0, 1));
            Assert.AreEqual(52f, layout.GetAvailableSpan(1, 1));
            Assert.AreEqual(24f, layout.GetAvailableSpan(2, 1));

            layout.SetArrangeLengthForPercents(100f);

            Assert.AreEqual(new Interval(0f, 24f), layout.GetArrangeInterval(0, 1));
            Assert.AreEqual(new Interval(24f, 76f), layout.GetArrangeInterval(1, 1));
            Assert.AreEqual(new Interval(76f, 100f), layout.GetArrangeInterval(2, 1));
        }
        #endregion
	}
}
